Add job categories - #3239
Conversation
Job categories are the job equivalent of [BenchmarkCategory]: they allow grouping jobs so that a subset of them can be selected, without relying on the job Id. - MetaMode.Categories, a hidden characteristic so that categories don't affect the generated job Id, the folder names, the summary nor the code generated for the child process - Job.WithCategory (adds) and Job.WithCategories (overrides), mirroring WithEnvironmentVariable/WithEnvironmentVariables - [JobCategory] attribute, which adds its categories to every job defined for the given class or assembly. It's implemented as a mutator job, so ImmutableConfigBuilder now merges categories instead of overriding them - JobCategoryFilter, which selects the benchmarks of the jobs that belong to any of the given categories
Replaced [JobCategory] with the Categories property in SimpleJob attributes, allowing multiple categories to be set inline. Updated documentation to clarify that categories do not affect job execution details.
Deleted the JobCategoryAttribute.cs file, including all using directives, class definition, constructors, and logic for applying job categories to jobs via attributes. This removes support for assigning categories to jobs through this attribute.
Refactor JobConfigBaseAttribute to use lazy config initialization and support job categories. Add a Categories property for job filtering and update constructors to accommodate these changes. Improve comments and code clarity.
Previously, job categories were explicitly preserved and re-added after applying mutator jobs to ensure they were not lost. This logic has been removed, and mutators are now applied directly without restoring categories.
Replaced WithTwoJobsAndACategory with WithTwoCategorizedJobs using explicit Categories in SimpleJob attributes. Added tests for category assignment, jobs without categories, category-independent job IDs, and category-based filtering. Introduced new test classes and removed obsolete tests and attributes.
|
@timcassell |
|
Hi @timcassell, please any updates on this PR? |
|
Thanks for the PR! I went through the diff (merge-base Categories affect job identity but not the job name
The result is that two jobs differing only by category survive Without a
|
Refactored the Categories property to be init-only and nullable (string[]?), enforcing immutability after initialization. Updated Config property logic to handle null or empty Categories safely. Added remarks to clarify attribute usage and rationale for these changes.
Updated job selection logic to group jobs by equality (excluding categories) and merge their categories, replacing Distinct with JobComparer. Added MergeCategories method to ensure all categories are preserved, preventing mismatches when filtering jobs by category.
The comparison logic for jobs now ignores the MetaMode.CategoriesCharacteristic field. This change prevents jobs that differ only by category from being treated as distinct, ensuring the same job isn't run multiple times under different names.
Updated the WithCategories extension for Job to throw ArgumentNullException if categories is null. This improves error handling and prevents potential runtime exceptions.
Updated the Categories property setter to set the value to null if the input is null or results in an empty set after removing duplicates. This change ensures jobs with no categories are treated the same as those never assigned categories, preventing unnecessary updates during category selection.
Expanded and clarified the BenchmarkDotNet job category test suite. Renamed and rewrote the deduplication test to verify merging of categories. Added tests for ordering (ignoring categories), handling empty and null categories, and correct exception parameter naming. Introduced a new test class for null category scenarios to ensure robust and correct category handling.
|
Hi @timcassell the finds you outlined have now been fixed. Addressed the findings around job categories, deduplication, null handling, and configuration mutability.
|
|
Re-reviewed at
Taking both routes for the identity problem — skipping the characteristic in Four things left, none blocking: 1. A mutator carrying categories wipes the target's categories. 2. 3. 4. One related design question worth settling explicitly, since the docs are the place users will look: applying Reviewed by Claude (Opus 5), posted by @timcassell. |
Updated docs to explain three methods for filtering jobs by category: JobCategoryFilter in code, [JobCategoryFilter] attribute, and --jobCategories argument. Added code and CLI examples. Clarified that filters are inclusion-only and jobs without categories are excluded unless assigned.
Updated documentation to describe the new --jobCategories console argument. This option enables running benchmarks for jobs in specified categories, excluding uncategorized jobs. Changes include updates to the usage list and detailed options section.
Introduced JobCategoryFilterAttribute in BenchmarkDotNet.Attributes to enable filtering benchmarks by job categories. Includes constructors for CLS compliance and category specification, XML documentation, and PublicAPI annotation.
Previously, mutating jobs could overwrite existing categories, leading to loss of category information. Now, the original categories are saved, the mutator is applied, and both sets of categories are combined to ensure correct job selection by category.
Added JobCategories property to CommandLineOptions for filtering benchmarks by job category. Updated UserProvidedFilters logic to recognize JobCategories as a user-provided filter.
Added support for filtering benchmarks by job categories in the configuration parser. If job categories are specified in the options, a JobCategoryFilter is created and applied, enabling selective benchmark execution.
Added a detailed <remarks> section to the JobCategoryFilter class summary. The new remarks clarify that the filter is inclusion-only and explain how benchmarks with uncategorized jobs are handled when filtering by category. No code logic was changed.
Refactored the WithCategories method in BenchmarkDotNet.Jobs to a single-line expression-bodied method, removing the explicit ArgumentNullException check for the categories parameter.
Improved validation and error handling in BenchmarkDotNet.Jobs.MetaMode. AddCategories now throws ArgumentNullException for null input. Unique method checks for null input and null categories, throwing exceptions as needed. Updated comments to clarify validation and merging logic.
Added extensive tests to JobCategoryTests.cs covering category merging, handling of null/empty categories, and category filtering via attributes and console arguments. Ensured categories are additive, invalid inputs are rejected, and introduced supporting test classes and attributes.
Issue #3182
Follow-up to the discussion in #3216, and a step towards #3182.
What this adds
This PR introduces job categories to provide a way to group and filter jobs, similar to [BenchmarkCategory].
cc @filzrev @adamsitnik @timcassell